#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
优化版日志模块集成示例

本文件展示了如何在租赁系统的典型业务场景中集成和使用优化版日志模块。
包含合同管理、租金处理、数据导入等核心业务功能的日志记录最佳实践。
"""

import os
import sys
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any

# 导入优化版日志模块
# 使用通配符导入确保兼容性
from optimized_logging import *

# 手动验证关键函数存在，避免运行时错误
try:
    # 确保所有必要的函数都可用
    required_functions = [
        'log_debug', 'log_info', 'log_warning', 'log_error', 'log_critical', 'log_exception',
        'record_operation', 'record_login', 'record_logout',
        'record_contract_operation', 'record_rent_record_operation',
        'record_system_setting_change', 'flush_operation_logs',
        'log_exceptions', 'log_performance', 'LogContext'
    ]
    
    for func_name in required_functions:
        if func_name not in dir():
            print(f"警告: 缺少必要函数 {func_name}", file=sys.stderr)
except Exception as e:
    print(f"导入日志模块时发生警告: {e}", file=sys.stderr)


# =============================================================================
# 示例1: 合同管理功能日志集成
# =============================================================================

class ContractManager:
    """合同管理类示例"""
    
    def __init__(self):
        """初始化合同管理器"""
        log_info("合同管理器已初始化")
    
    @log_exceptions
    def create_contract(self, contract_data: Dict, operator: str) -> str:
        """
        创建新合同
        
        Args:
            contract_data: 合同数据
            operator: 操作人
            
        Returns:
            str: 合同编号
        """
        # 添加上下文信息，包含关键业务数据
        context = {
            'operator': operator,
            'property_id': contract_data.get('property_id'),
            'tenant_id': contract_data.get('tenant_id'),
            'start_date': contract_data.get('start_date')
        }
        
        log_info("开始创建合同", context=context)
        
        # 模拟合同创建过程
        try:
            # 验证数据
            if not contract_data.get('contract_no'):
                # 生成合同编号
                contract_no = f"HT-{datetime.now().year}-{datetime.now().strftime('%m%d')}-001"
                contract_data['contract_no'] = contract_no
            else:
                contract_no = contract_data['contract_no']
            
            # 模拟保存到数据库
            log_debug(f"准备保存合同数据: {contract_data.keys()}", context={'contract_no': contract_no})
            time.sleep(0.1)  # 模拟处理时间
            
            # 记录操作日志
            record_contract_operation(
                username=operator,
                contract_no=contract_no,
                operation_type="创建",
                success=True,
                detail={
                    'property_id': contract_data.get('property_id'),
                    'tenant_id': contract_data.get('tenant_id'),
                    'rent_amount': contract_data.get('rent_amount')
                }
            )
            
            log_info("合同创建成功", context={'contract_no': contract_no})
            return contract_no
            
        except Exception as e:
            # 发生异常时会被@log_exceptions装饰器自动捕获并记录
            # 这里只需要记录操作日志
            record_contract_operation(
                username=operator,
                contract_no=contract_data.get('contract_no', '未知'),
                operation_type="创建",
                success=False,
                detail={'error': str(e)}
            )
            raise
    
    @log_performance(threshold=0.3)  # 超过0.3秒记录性能日志
    def batch_update_contracts(self, contract_ids: List[str], update_data: Dict, operator: str) -> Dict:
        """
        批量更新合同
        
        Args:
            contract_ids: 合同ID列表
            update_data: 更新数据
            operator: 操作人
            
        Returns:
            Dict: 处理结果
        """
        context = {
            'operator': operator,
            'contract_count': len(contract_ids),
            'update_fields': list(update_data.keys())
        }
        
        log_info("开始批量更新合同", context=context)
        
        # 使用上下文管理器跟踪整个批量操作
        with LogContext("批量合同更新", log_level="INFO"):
            success_count = 0
            failed_count = 0
            failed_ids = []
            
            # 模拟批量更新
            for contract_id in contract_ids:
                try:
                    log_debug(f"更新合同: {contract_id}")
                    # 模拟处理时间
                    if contract_id.endswith('3'):  # 模拟某些合同更新失败
                        raise ValueError(f"合同 {contract_id} 更新失败")
                    time.sleep(0.1)
                    success_count += 1
                except Exception as e:
                    failed_count += 1
                    failed_ids.append(contract_id)
                    log_error(f"更新合同失败: {contract_id}", context={'error': str(e)})
            
            # 记录整体操作日志
            record_operation(
                username=operator,
                operation_module="合同管理",
                operation_content="批量更新合同",
                operation_result="部分成功" if failed_count > 0 else "成功",
                detail={
                    'total': len(contract_ids),
                    'success': success_count,
                    'failed': failed_count,
                    'failed_ids': failed_ids,
                    'update_fields': list(update_data.keys())
                }
            )
            
            result = {
                'total': len(contract_ids),
                'success': success_count,
                'failed': failed_count,
                'failed_ids': failed_ids
            }
            
            log_info("批量更新完成", context=result)
            return result


# =============================================================================
# 示例2: 租金处理功能日志集成
# =============================================================================

class RentProcessor:
    """租金处理器类示例"""
    
    @log_exceptions
    def process_rent_collection(self, contract_no: str, amount: float, payment_date: str, 
                               operator: str, payment_method: str = "现金") -> Dict:
        """
        处理租金收取
        
        Args:
            contract_no: 合同编号
            amount: 金额
            payment_date: 支付日期
            operator: 操作人
            payment_method: 支付方式
            
        Returns:
            Dict: 处理结果
        """
        # 复杂业务场景使用上下文管理器
        with LogContext(f"租金收取-{contract_no}") as log_ctx:
            context = {
                'contract_no': contract_no,
                'amount': amount,
                'payment_date': payment_date,
                'operator': operator,
                'payment_method': payment_method
            }
            
            log_info("开始处理租金收取", context=context)
            
            # 模拟业务处理
            try:
                # 验证合同
                log_debug("验证合同信息", context={'contract_no': contract_no})
                time.sleep(0.1)
                
                # 检查是否重复收取
                is_duplicate = False  # 模拟检查结果
                if is_duplicate:
                    raise ValueError("该日期的租金已收取")
                
                # 记录租金收入
                receipt_no = f"R-{datetime.now().strftime('%Y%m%d%H%M%S')}"
                log_info("生成收据号", context={'receipt_no': receipt_no})
                
                # 模拟保存到数据库
                time.sleep(0.15)
                
                # 记录操作日志
                record_rent_record_operation(
                    username=operator,
                    contract_no=contract_no,
                    operation_type="收取租金",
                    success=True,
                    detail={
                        'amount': amount,
                        'payment_date': payment_date,
                        'payment_method': payment_method,
                        'receipt_no': receipt_no
                    }
                )
                
                result = {
                    'success': True,
                    'receipt_no': receipt_no,
                    'contract_no': contract_no,
                    'amount': amount
                }
                
                log_info("租金收取处理成功", context=result)
                return result
                
            except Exception as e:
                # 记录失败的操作日志
                record_rent_record_operation(
                    username=operator,
                    contract_no=contract_no,
                    operation_type="收取租金",
                    success=False,
                    detail={
                        'amount': amount,
                        'payment_date': payment_date,
                        'error': str(e)
                    }
                )
                # 异常会被@log_exceptions装饰器处理并重新抛出
                raise


# =============================================================================
# 示例3: 用户认证日志集成
# =============================================================================

def authenticate_user(username: str, password: str) -> Dict:
    """
    用户认证函数示例
    
    Args:
        username: 用户名
        password: 密码
        
    Returns:
        Dict: 认证结果
    """
    context = {
        'username': username,
        'timestamp': datetime.now().isoformat()
    }
    
    log_info("用户认证尝试", context=context)
    
    try:
        # 模拟认证逻辑
        is_valid = username == "admin" and password == "password123"  # 示例，实际应使用安全认证
        
        if is_valid:
            # 认证成功
            user_info = {
                'user_id': '1001',
                'username': username,
                'role': '管理员'
            }
            
            # 记录登录成功日志
            record_login(
                username=username,
                success=True,
                detail={
                    'user_id': user_info['user_id'],
                    'role': user_info['role']
                }
            )
            
            log_info("用户认证成功", context=user_info)
            return {
                'success': True,
                'user_info': user_info
            }
        else:
            # 认证失败
            record_login(
                username=username,
                success=False,
                detail={'reason': '用户名或密码错误'}
            )
            
            log_warning("用户认证失败", context={'username': username})
            return {
                'success': False,
                'message': '用户名或密码错误'
            }
            
    except Exception as e:
        log_exception(e, "用户认证过程出错", context=context)
        record_login(
            username=username,
            success=False,
            detail={'reason': '系统错误'}
        )
        return {
            'success': False,
            'message': '认证过程中发生错误'
        }


def logout_user(username: str):
    """
    用户登出函数示例
    
    Args:
        username: 用户名
    """
    try:
        record_logout(username)
        log_info("用户登出", context={'username': username})
        return True
    except Exception as e:
        log_error("记录用户登出失败", context={'username': username, 'error': str(e)})
        return False


# =============================================================================
# 示例4: 系统设置变更日志集成
# =============================================================================

def update_system_setting(setting_name: str, new_value: Any, operator: str) -> bool:
    """
    更新系统设置
    
    Args:
        setting_name: 设置名称
        new_value: 新值
        operator: 操作人
        
    Returns:
        bool: 是否成功
    """
    # 模拟获取旧值
    old_value = "默认值"  # 实际应该从配置中读取
    
    context = {
        'setting_name': setting_name,
        'old_value': old_value,
        'new_value': new_value,
        'operator': operator
    }
    
    log_info("开始更新系统设置", context=context)
    
    try:
        # 验证设置值
        if setting_name == "max_retries" and not isinstance(new_value, int):
            raise ValueError("重试次数必须是整数")
        
        # 模拟保存设置
        time.sleep(0.1)
        
        # 记录设置变更日志
        record_system_setting_change(
            username=operator,
            setting_name=setting_name,
            old_value=old_value,
            new_value=new_value,
            success=True
        )
        
        log_info("系统设置更新成功", context=context)
        return True
        
    except Exception as e:
        # 记录失败的设置变更
        record_system_setting_change(
            username=operator,
            setting_name=setting_name,
            old_value=old_value,
            new_value=new_value,
            success=False
        )
        
        log_exception(e, "更新系统设置失败", context=context)
        return False


# =============================================================================
# 示例5: 批量数据导入日志集成
# =============================================================================

@log_performance(threshold=1.0)  # 大型导入可能耗时较长
@log_exceptions
def import_data_from_file(file_path: str, data_type: str, operator: str) -> Dict:
    """
    从文件导入数据
    
    Args:
        file_path: 文件路径
        data_type: 数据类型
        operator: 操作人
        
    Returns:
        Dict: 导入结果
    """
    # 使用LogContext在函数内部而不是外部
    with LogContext("批量数据导入"):
        context = {
            'file_path': file_path,
            'data_type': data_type,
            'operator': operator
        }
        
        log_info("开始导入数据", context=context)
        
        try:
            # 检查文件是否存在
            if not os.path.exists(file_path):
                raise FileNotFoundError(f"文件不存在: {file_path}")
            
            # 模拟读取文件和处理数据
            total_count = 100  # 模拟总记录数
            success_count = 0
            failed_count = 0
            errors = []
            
            # 模拟处理批次
            batch_size = 20
            for batch in range(0, total_count, batch_size):
                batch_context = {
                    'batch': batch // batch_size + 1,
                    'batch_size': batch_size,
                    'current_count': min(batch + batch_size, total_count)
                }
                
                log_debug("处理数据批次", context=batch_context)
                
                # 模拟处理时间
                time.sleep(0.2)
                
                # 模拟部分失败记录
                batch_success = batch_size - (1 if batch == 40 else 0)
                success_count += batch_success
                failed_count += batch_size - batch_success
                
                if batch == 40:
                    error_msg = f"批次 {batch//batch_size + 1} 中有1条记录格式错误"
                    errors.append(error_msg)
                    log_warning(error_msg, context=batch_context)
            
            # 记录操作日志
            record_operation(
                username=operator,
                operation_module="数据导入",
                operation_content=f"导入{data_type}数据",
                operation_result="部分成功" if failed_count > 0 else "成功",
                detail={
                    'file_path': file_path,
                    'total': total_count,
                    'success': success_count,
                    'failed': failed_count,
                    'errors': errors
                }
            )
            
            result = {
                'total': total_count,
                'success': success_count,
                'failed': failed_count,
                'errors': errors
            }
            
            log_info("数据导入完成", context=result)
            return result
            
        except Exception as e:
            # 记录导入失败
            record_operation(
                username=operator,
                operation_module="数据导入",
                operation_content=f"导入{data_type}数据",
                operation_result="失败",
                detail={
                    'file_path': file_path,
                    'error': str(e)
                }
            )
            raise


# =============================================================================
# 运行示例
# =============================================================================

def run_examples():
    """
    运行所有示例
    """
    import time
    
    print("开始运行优化版日志模块集成示例...\n")
    
    # 示例1: 合同管理
    print("示例1: 合同管理")
    print("-" * 50)
    
    contract_manager = ContractManager()
    
    # 创建单个合同
    try:
        contract_data = {
            'property_id': 'PROP001',
            'tenant_id': 'TENANT001',
            'rent_amount': 3500.00,
            'start_date': '2024-11-01',
            'end_date': '2025-11-01'
        }
        
        contract_no = contract_manager.create_contract(contract_data, "admin")
        print(f"创建合同成功，合同编号: {contract_no}")
        
    except Exception as e:
        print(f"创建合同失败: {str(e)}")
    
    # 批量更新合同
    try:
        update_result = contract_manager.batch_update_contracts(
            ['HT-2024-1101-001', 'HT-2024-1101-002', 'HT-2024-1101-003'],
            {'status': 'active', 'updated_by': 'admin'},
            "admin"
        )
        print(f"批量更新结果: 成功{update_result['success']}条，失败{update_result['failed']}条")
        
    except Exception as e:
        print(f"批量更新失败: {str(e)}")
    
    print()
    
    # 示例2: 租金处理
    print("示例2: 租金处理")
    print("-" * 50)
    
    rent_processor = RentProcessor()
    try:
        rent_result = rent_processor.process_rent_collection(
            contract_no="HT-2024-1101-001",
            amount=3500.00,
            payment_date="2024-11-01",
            operator="admin",
            payment_method="转账"
        )
        print(f"租金收取成功，收据号: {rent_result['receipt_no']}")
        
    except Exception as e:
        print(f"租金收取失败: {str(e)}")
    
    print()
    
    # 示例3: 用户认证
    print("示例3: 用户认证")
    print("-" * 50)
    
    # 测试成功登录
    auth_result = authenticate_user("admin", "password123")
    print(f"登录结果: {'成功' if auth_result['success'] else '失败'}")
    
    # 测试失败登录
    auth_result = authenticate_user("admin", "wrong_password")
    print(f"登录结果: {'成功' if auth_result['success'] else '失败'}")
    
    # 测试登出
    logout_success = logout_user("admin")
    print(f"登出结果: {'成功' if logout_success else '失败'}")
    
    print()
    
    # 示例4: 系统设置
    print("示例4: 系统设置更新")
    print("-" * 50)
    
    setting_result = update_system_setting("max_retries", 5, "admin")
    print(f"更新设置结果: {'成功' if setting_result else '失败'}")
    
    # 测试错误的设置值
    setting_result = update_system_setting("max_retries", "not_an_int", "admin")
    print(f"更新设置结果: {'成功' if setting_result else '失败'}")
    
    print()
    
    # 示例5: 数据导入
    print("示例5: 数据导入")
    print("-" * 50)
    
    # 注意: 这里只是模拟文件导入，实际运行会因为文件不存在而失败
    try:
        import_data_from_file("dummy_data.csv", "租户信息", "admin")
    except Exception as e:
        print(f"导入测试完成，预期的文件不存在异常: {type(e).__name__}")
    
    print()
    print("\n所有示例运行完成！请查看logs目录下的日志文件以查看详细的日志记录。")
    
    # 强制刷新所有日志
    flush_operation_logs()
    print("操作日志已刷新到数据库。")


if __name__ == "__main__":
    run_examples()
